package com.delivery.utils;

import com.alibaba.fastjson.JSONObject;
import com.delivery.config.WxPayConfig;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;

@Slf4j
@Component
public class WxMiniPayUtils {

    @Autowired
    WxPayConfig autoWxPayConfig;
    public static WxPayConfig wxPayConfig;

    public static CloseableHttpClient httpClient;

    public static Verifier verifier;

    @PostConstruct
    public void inte(){
        wxPayConfig = autoWxPayConfig;
    }

    /**
     * 初始化 HttpClient
     * @throws IOException
     */
    public static void initWXPayClient() {
        try {
            // 加载商户私钥（privateKey：私钥字符串）
            PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey( new ClassPathResource(wxPayConfig.getPrivateKeyPath()).getInputStream() );

            // 也可使用证书 查询商户证书序列号
//            X509Certificate wechatPayCert = PemUtil.loadCertificate(new ByteArrayInputStream(StaticVariable.WX_PAY_CERT.getBytes(StandardCharsets.UTF_8)));
//            String serialNo = wechatPayCert.getSerialNumber().toString(16).toUpperCase();

            //merchantId:商户号,serialNo:商户证书序列号
            String serialNo = wxPayConfig.getSerialNo();
            String merchantId = wxPayConfig.getMchId();

            // 获取证书管理器实例
            CertificatesManager certificatesManager = CertificatesManager.getInstance();
            // 向证书管理器增加需要自动更新平台证书的商户信息
            certificatesManager.putMerchant(merchantId, new WechatPay2Credentials(merchantId,
                    new PrivateKeySigner(serialNo, merchantPrivateKey)), wxPayConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8));
            // 从证书管理器中获取verifier
            //版本>=0.4.0可使用 CertificatesManager.getVerifier(mchId) 得到的验签器替代默认的验签器。
            // 它会定时下载和更新商户对应的微信支付平台证书 （默认下载间隔为UPDATE_INTERVAL_MINUTE）。
            verifier = certificatesManager.getVerifier(merchantId);

            //创建一个httpClient
            httpClient = WechatPayHttpClientBuilder.create()
                    .withMerchant(merchantId, serialNo, merchantPrivateKey)
                    .withValidator(new WechatPay2Validator(verifier)).build();
        } catch (IOException e) {
            e.printStackTrace();
            log.error("加载秘钥文件失败");
        } catch (GeneralSecurityException e) {
            e.printStackTrace();
            log.error("获取平台证书失败");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 关闭 HttpClient
     * @throws IOException
     */
    public static void closeWXClient() throws IOException {
        if (httpClient != null) {
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 创建微信支付订单
     * @param openId 用户唯一标识
     * @param orderId 订单id
     * @param amount 支付价格(单位分)
     * @param description 订单说明
     * @return
     * @throws Exception
     */
    public static String creatOrderJSAPI(String openId,String orderId,Integer amount,Integer attach,String description) throws Exception {
        try {

            initWXPayClient();
            HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi");
            httpPost.addHeader("Accept", "application/json");
            httpPost.addHeader("Content-type", "application/json; charset=utf-8");

            String reqdata = "{"
                    + "\"amount\": {"
                    + "\"total\": "+ amount+ ","
                    + "\"currency\": \"CNY\""
                    + "},"
                    + "\"attach\": \""+ attach +"\","
                    + "\"mchid\": \""+ wxPayConfig.getMchId() +"\","
                    + "\"description\": \""+ description  +"\","
                    + "\"notify_url\": \""+ wxPayConfig.getNotifyDomain() +"\","
                    + "\"payer\": {"
                    + "\"openid\": \""+openId+"\"" + "},"
                    + "\"out_trade_no\": \""+orderId+"\","
                    + "\"goods_tag\": \"WXG\","
                    + "\"appid\": \""+ wxPayConfig.getAppid() +"\"" + "}";

            httpPost.setEntity(new StringEntity(reqdata, "utf-8"));
            CloseableHttpResponse response = httpClient.execute(httpPost);
            String bodyAsString = EntityUtils.toString(response.getEntity());
            return bodyAsString;
        }catch (Exception e){
            e.printStackTrace();
            log.error("创建微信支付订单失败");
        }finally {
            closeWXClient();
        }
        return "";
    }

    public static void closeOrder(String code) throws IOException {
        // 更改腾讯支付订单的状态
        String url = "https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/"+ code +"/close";
        JSONObject body = new JSONObject();
        body.put("mchid", wxPayConfig.getMchId());
        initWXPayClient();
        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type", "application/json; charset=utf-8");
        httpPost.setEntity(new StringEntity(body.toString(), "utf-8"));
        httpClient.execute(httpPost);
    }


    public static String v3Post(String url,String body) throws Exception {
        log.info("微信v3 post请求参数:" + body);
        initWXPayClient();

        HttpPost httpPost = new HttpPost(url);
        httpPost.addHeader("Accept", "application/json");
        httpPost.addHeader("Content-type", "application/json; charset=utf-8");

        httpPost.addHeader("Wechatpay-Serial", wxPayConfig.getSerialNo());
        httpPost.setEntity(new StringEntity(body, "UTF-8"));
        CloseableHttpResponse response = httpClient.execute(httpPost);
        try {
            String bodyAsString = EntityUtils.toString(response.getEntity());
            log.info("微信v3 post请求返回信息：" + bodyAsString);
            return bodyAsString;
        } finally {
            closeWXClient();
            response.close();
        }

    }



}
